﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using ActionService.ServiceContracts;
using System.Configuration;
using DataObjects.Interface;
using DataObjects;
using DataObjects.Interface.Person;
using ActionService.Messages;
using ActionService.MessageBase;
using ActionService.Criteria;
using ActionService.DataTransferObjects;
using DataObjects.Interface.Admin;
using ActionService.DataTransferObjectMapper;
using BusinessObjects.Person;
using BusinessObjects;
using DataObjects.Interface.Production;
using BusinessObjects.Production;
using System.Transactions;
using DataObjects.Interface.HumanResources;
using BusinessObjects.HumanResources;
using DataObjects.Interface.Sales;

namespace ActionService.ServiceImplementations
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
    public class ActionService : IActionService
    {
        #region Create static data access objects

        private static readonly IAccountingObjectDao _accountingObjectDao = DataAccess.AccountingObjectDao;
        private static readonly IUserGroupDao _userGroupDao = DataAccess.UserGroupsDao;
        private static readonly IRestaurantDao _restaurantsDao = DataAccess.RestaurantDao;
        private static readonly IAccountingObjectCategoryDao _accountingObjectCategoryDao = DataAccess.AccountingObjectCategoryDao;
        private static readonly ICountryRegionDao _countryRegionDao = DataAccess.CountryRegionDao;
        private static readonly IDistrictDao _districtDao = DataAccess.DistrictsDao;
        private static readonly IProvincesDao _provinceDao = DataAccess.ProvincesDao;
        private static readonly IInventoryItemCategoryDao _inventoryItemCategoryDao = DataAccess.InventoryItemCategoryDao;
        private static readonly IInventoryItemDao _inventoryItemDao = DataAccess.InventoryItemDao;
        private static readonly IStockDao _stockDao = DataAccess.StockDao;
        private static readonly IUnitsDao _unitsDao = DataAccess.UnitsDao;
        private static readonly IRestaurantAreaDao _restaurantAreaDao = DataAccess.RestaurantAreaDao;
        private static readonly IRestaurantTableDao _restaurantTableDao = DataAccess.RestaurantTableDao;
        private static readonly IRestaurantMenuCategoryDao _restaurantMenuCategoryDao = DataAccess.RestaurantMenuCategoryDao;
        private static readonly IRestaurantMenuDao _restaurantMenuDao = DataAccess.RestaurantMenuDao;
        private static readonly IRestaurantMenuNormDao _restaurantMenuNormDao = DataAccess.RestaurantMenuNormDao;
        private static readonly IRestaurantMenuNormDetailDao _restaurantMenuNormDetailDao = DataAccess.RestaurantMenuNormDetailDao;
        private static readonly ICurrencyDao _currencyDao = DataAccess.CurrencyDao;
        private static readonly IDepartmentDao _departmentDao = DataAccess.DepartmentDao;
        private static readonly ITimeSheetSignDao _timeSheetSignDao = DataAccess.TimeSheetSignDao;
        private static readonly IShipMethodDao _shipMethodDao = DataAccess.ShipMethodDao;
        private static readonly IAutoIdDao _autoIdDao = DataAccess.AutoIDDao;
        private static readonly IInwardOutwardDao _inwardOutwardDao = DataAccess.InwardOutwardDao;
        private static readonly IInwardOutwardDetailDao _inwardOutwardDetailDao = DataAccess.InwardOutwardDetailDao;
        private static readonly IInventoryLedgerDao _inventoryLedgerDao = DataAccess.InventoryLedgerDao;
        private static readonly IGeneralLedgerDao _generalLedgerDao = DataAccess.GeneralLedgerDao;
        #endregion

        // Session state variables
        private string _accessToken;
        private string _userName;
        private string _restaurantId;

        public TokenResponse GetToken(TokenRequest request)
        {
            var response = new TokenResponse(request.RequestId);

            // Validate client tag only
            if (!ValidRequest(request, response, Validate.ClientTag))
                return response;

            // Note: these are session based and expire when session expires.
            _accessToken = Guid.NewGuid().ToString();

            response.AccessToken = _accessToken;
            return response;
        }

        public LoginResponse Login(LoginRequest request)
        {
            var response = new LoginResponse(request.RequestId);

            // Validate client tag and access token
            if (!ValidRequest(request, response, Validate.ClientTag | Validate.AccessToken))
                return response;
            else
                response.RestaurantID = request.RestaurantID;
            //if (!Membership.ValidateUser(request.UserName, request.Password))
            //{
            //    response.Acknowledge = AcknowledgeType.Failure;
            //    response.Message = "Tên đăng nhập/ mật khẩu không hợp lệ";
            //    return response;
            //}

            _userName = request.UserName;
            _restaurantId = request.RestaurantID;

            return response;
        }

        public LogoutResponse Logout(LogoutRequest request)
        {
            var response = new LogoutResponse(request.RequestId);

            // Validate client tag and access token
            if (!ValidRequest(request, response, Validate.ClientTag | Validate.AccessToken))
                return response;

            _userName = null;

            return response;
        }

        public UserGroupResponse GetUserGroups(UserGroupRequest request)
        {
            var response = new UserGroupResponse(request.RequestId);

            // Validate client tag, access token, and user credentials
            if (!ValidRequest(request, response, Validate.All))
                return response;

            var criteria = request.Criteria as UserGroupCriteria;

            if (request.LoadOptions.Contains("UserGroups"))
            {
                if (request.LoadOptions.Contains("NoImage"))
                {
                    IEnumerable<UserGroup> userGroups;
                    userGroups = _userGroupDao.GetUserGroupsNoImage();
                    response.UserGroups = userGroups.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else
                {
                    IEnumerable<UserGroup> userGroups;
                    userGroups = _userGroupDao.GetUserGroups();
                    response.UserGroups = userGroups.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
            }

            if (request.LoadOptions.Contains("UserGroup"))
            {
                var userGroup = _userGroupDao.GetUserGroup(criteria.UserGroupId);
                response.UserGroup = Mapper.ToDataTransferObject(userGroup);
            }

            if (request.LoadOptions.Contains("UserGroupsByBranch"))
            {

                IEnumerable<UserGroup> userGroups;
                userGroups = _userGroupDao.GetUserGroupByBranch(request.RestaurantID);
                response.UserGroups = userGroups.Select(c => Mapper.ToDataTransferObject(c)).ToList();
            }

            return response;
        }

        public UserGroupResponse SetUserGroups(UserGroupRequest request)
        {
            var response = new UserGroupResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.All))
                return response;
            var userGroup = Mapper.FromDataTransferObject(request.UserGroup);

            if (request.Action != "Delete")
            {
                if (!userGroup.Validate())
                {
                    foreach (string error in userGroup.ValidationErrors)
                        response.Message += error + Environment.NewLine;
                    response.Acknowledge = AcknowledgeType.Failure;
                    return response;
                }
            }
            try
            {
                if (request.Action == "Create") { _userGroupDao.InsertUserGroup(userGroup); }
                else if (request.Action == "Update") { _userGroupDao.UpdateUserGroup(userGroup); }
                else
                {
                    var criteria = request.Criteria as UserGroupCriteria;
                    var _userGroup = _userGroupDao.GetUserGroup(criteria.UserGroupId);
                    _userGroupDao.DeleteUserGroup(_userGroup);
                }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
                return response;
            }

            response.Acknowledge = AcknowledgeType.Success;
            response.RowsAffected = 1;

            return response;
        }

        public AccountingObjectCategoryResponse GetAccountingObjectCategories(AccountingObjectCategoryRequest request)
        {
            var response = new AccountingObjectCategoryResponse(request.RequestId);

            // Validate client tag, access token, and user credentials
            if (!ValidRequest(request, response, Validate.All))
                return response;

            var criteria = request.Criteria as AccountingObjectCategoryCriteria;

            if (request.LoadOptions.Contains("AcountingObjectCategories"))
            {
                IEnumerable<AccountingObjectCategory> acountingObjectCategories;
                acountingObjectCategories = _accountingObjectCategoryDao.GetAccountingObjectCategories();
                response.AccountingObjectCategories = acountingObjectCategories.Select(c => Mapper.ToDataTransferObject(c)).ToList();
            }

            if (request.LoadOptions.Contains("AcountingObjectCategory"))
            {
                var acountingObjectCategory = _accountingObjectCategoryDao.GetAccountingObjectCategory(criteria.AccountingObjectCategoryID);
                response.AccountingObjectCategory = Mapper.ToDataTransferObject(acountingObjectCategory);
            }

            if (request.LoadOptions.Contains("AcountingObjectCategoryByBranch"))
            {

                AccountingObjectCategory acountingObjectCategory;
                acountingObjectCategory = _accountingObjectCategoryDao.GetAccountingObjectCategoryByBranch(request.RestaurantID, criteria.AccountingObjectCategoryID);
                response.AccountingObjectCategory = Mapper.ToDataTransferObject(acountingObjectCategory);
            }

            if (request.LoadOptions.Contains("AcountingObjectCategoriesByBranch"))
            {
                if (request.LoadOptions.Contains("Active"))
                {
                    IEnumerable<AccountingObjectCategory> acountingObjectCategories;
                    acountingObjectCategories = _accountingObjectCategoryDao.GetAccountingObjectCategoriesByBranchAndIsActive(request.RestaurantID, criteria.IsCustomer, criteria.IsVendor, criteria.IsEmployee, true);
                    response.AccountingObjectCategories = acountingObjectCategories.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("NonActive"))
                {
                    IEnumerable<AccountingObjectCategory> acountingObjectCategories;
                    acountingObjectCategories = _accountingObjectCategoryDao.GetAccountingObjectCategoriesByBranchAndIsActive(request.RestaurantID, criteria.IsCustomer, criteria.IsVendor, criteria.IsEmployee, false);
                    response.AccountingObjectCategories = acountingObjectCategories.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else
                {
                    IEnumerable<AccountingObjectCategory> acountingObjectCategories;
                    acountingObjectCategories = _accountingObjectCategoryDao.GetAccountingObjectCategoriesByBranch(request.RestaurantID, criteria.IsCustomer, criteria.IsVendor, criteria.IsEmployee);
                    response.AccountingObjectCategories = acountingObjectCategories.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
            }

            return response;
        }

        public AccountingObjectCategoryResponse SetAccountingObjectCategories(AccountingObjectCategoryRequest request)
        {
            var response = new AccountingObjectCategoryResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.All))
                return response;
            var accountingObjectCategory = Mapper.FromDataTransferObject(request.AccountingObjectCategory);

            if (request.Action != "Delete")
            {
                if (!accountingObjectCategory.Validate())
                {
                    foreach (string error in accountingObjectCategory.ValidationErrors)
                        response.Message += error + Environment.NewLine;
                    response.Acknowledge = AcknowledgeType.Failure;
                    return response;
                }
            }
            try
            {
                if (request.Action == "Create") { _accountingObjectCategoryDao.InsertAccountingObjectCategory(accountingObjectCategory); }
                else if (request.Action == "Update") { _accountingObjectCategoryDao.UpdateAccountingObjectCategory(accountingObjectCategory); }
                else
                {
                    var criteria = request.Criteria as AccountingObjectCategoryCriteria;

                    if (_accountingObjectDao.GetCountAcountingObjectsByCategory(criteria.AccountingObjectCategoryID) > 0)
                    {
                        response.Acknowledge = AcknowledgeType.Failure;
                        response.Message = "Không thể xóa. Loại đối tượng có đối tượng con tương ứng !";
                        return response;
                    }
                    if (_accountingObjectCategoryDao.GetCountAcountingObjectCategoryByParentId(criteria.AccountingObjectCategoryID) > 0)
                    {
                        response.Acknowledge = AcknowledgeType.Failure;
                        response.Message = "Không thể xóa. Loại đối tượng có loại đối tượng con tương ứng !";
                        return response;
                    }

                    var _accountingObjectCategory = _accountingObjectCategoryDao.GetAccountingObjectCategory(criteria.AccountingObjectCategoryID);
                    _accountingObjectCategoryDao.DeleteAccountingObjectCategory(_accountingObjectCategory);
                }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
                return response;
            }

            response.Acknowledge = AcknowledgeType.Success;
            response.RowsAffected = 1;

            return response;
        }

        public CountryRegionResponse GetCountryRegions(CountryRegionRequest request)
        {
            var response = new CountryRegionResponse(request.RequestId);

            // Validate client tag, access token, and user credentials
            if (!ValidRequest(request, response, Validate.All))
                return response;

            var criteria = request.Criteria as CountryRegionCriteria;

            if (request.LoadOptions.Contains("CountryRegions"))
            {
                if (request.LoadOptions.Contains("Active"))
                {
                    IEnumerable<CountryRegion> countryRegions;
                    countryRegions = _countryRegionDao.GetCountryRegionsByIsActive(true);
                    response.CountryRegions = countryRegions.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("ByPage"))
                {
                    IEnumerable<CountryRegion> countryRegions;
                    countryRegions = _countryRegionDao.GetCountryRegionsByPage(criteria.CurrentPage);
                    response.CountryRegions = countryRegions.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else
                {
                    IEnumerable<CountryRegion> countryRegions;
                    countryRegions = _countryRegionDao.GetCountryRegions();
                    response.CountryRegions = countryRegions.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
            }

            if (request.LoadOptions.Contains("CountryRegion"))
            {
                var countryRegion = _countryRegionDao.GetCountryRegion(criteria.CountryRegionCode);
                response.CountryRegion = Mapper.ToDataTransferObject(countryRegion);
            }

            if (request.LoadOptions.Contains("TotalPage"))
            {
                var totalPage = _countryRegionDao.GetTotalPage();
                response.TotalPage = totalPage;
            }

            return response;
        }

        public CountryRegionResponse SetCountryRegions(CountryRegionRequest request)
        {
            var response = new CountryRegionResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.All))
                return response;
            var countryRegion = Mapper.FromDataTransferObject(request.CountryRegion);

            if (request.Action != "Delete")
            {
                if (!countryRegion.Validate())
                {
                    foreach (string error in countryRegion.ValidationErrors)
                        response.Message += error + Environment.NewLine;
                    response.Acknowledge = AcknowledgeType.Failure;
                    return response;
                }
            }
            try
            {
                if (request.Action == "Create") { _countryRegionDao.InsertCountryRegion(countryRegion); }
                else if (request.Action == "Update") { _countryRegionDao.UpdateCountryRegion(countryRegion); }
                else
                {
                    var criteria = request.Criteria as CountryRegionCriteria;
                    var _countryRegion = _countryRegionDao.GetCountryRegion(criteria.CountryRegionCode);
                    _countryRegionDao.DeleteCountryRegion(_countryRegion);
                }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
                return response;
            }

            response.Acknowledge = AcknowledgeType.Success;
            response.RowsAffected = 1;

            return response;
        }

        public DistrictResponse GetDistricts(DistrictRequest request)
        {
            var response = new DistrictResponse(request.RequestId);

            // Validate client tag, access token, and user credentials
            if (!ValidRequest(request, response, Validate.All))
                return response;

            var criteria = request.Criteria as DistrictCriteria;

            if (request.LoadOptions.Contains("Districts"))
            {
                if (request.LoadOptions.Contains("ByPage"))
                {
                    IEnumerable<District> districts;
                    districts = _districtDao.GetDistrictsByPage(criteria.CurrentPage);
                    response.Districts = districts.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("Active"))
                {
                    IEnumerable<District> districts;
                    districts = _districtDao.GetDistrictsByIsActive(true);
                    response.Districts = districts.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else
                {
                    IEnumerable<District> districts;
                    districts = _districtDao.GetDistricts();
                    response.Districts = districts.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
            }

            if (request.LoadOptions.Contains("District"))
            {
                var district = _districtDao.GetDistrict(criteria.DistrictCode);
                response.District = Mapper.ToDataTransferObject(district);
            }

            if (request.LoadOptions.Contains("TotalPage"))
            {
                var totalPage = _districtDao.GetTotalPage();
                response.TotalPage = totalPage;
            }

            return response;
        }

        public DistrictResponse SetDistricts(DistrictRequest request)
        {
            var response = new DistrictResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.All))
                return response;
            var district = Mapper.FromDataTransferObject(request.District);

            if (request.Action != "Delete")
            {
                if (!district.Validate())
                {
                    foreach (string error in district.ValidationErrors)
                        response.Message += error + Environment.NewLine;
                    response.Acknowledge = AcknowledgeType.Failure;
                    return response;
                }
            }
            try
            {
                if (request.Action == "Create") { _districtDao.InsertDistrict(district); }
                else if (request.Action == "Update") { _districtDao.UpdateDistrict(district); }
                else
                {
                    var criteria = request.Criteria as DistrictCriteria;
                    var _district = _districtDao.GetDistrict(criteria.DistrictCode);
                    _districtDao.DeleteDistrict(_district);
                }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
                return response;
            }

            response.Acknowledge = AcknowledgeType.Success;
            response.RowsAffected = 1;

            return response;
        }

        public ProvinceResponse GetProvinces(ProvinceRequest request)
        {
            var response = new ProvinceResponse(request.RequestId);

            // Validate client tag, access token, and user credentials
            if (!ValidRequest(request, response, Validate.All))
                return response;

            var criteria = request.Criteria as ProvinceCriteria;

            if (request.LoadOptions.Contains("Provinces"))
            {
                if (request.LoadOptions.Contains("Active"))
                {
                    IEnumerable<Province> provinces;
                    provinces = _provinceDao.GetProvincesByIsActive(true);
                    response.Provinces = provinces.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("ByPage"))
                {
                    IEnumerable<Province> provinces;
                    provinces = _provinceDao.GetProvincesByPage(criteria.CurrentPage);
                    response.Provinces = provinces.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
            }

            if (request.LoadOptions.Contains("Province"))
            {
                var province = _provinceDao.GetProvince(criteria.ProvinceCode);
                response.Province = Mapper.ToDataTransferObject(province);
            }

            if (request.LoadOptions.Contains("TotalPage"))
            {
                var totalPage = _provinceDao.GetTotalPage();
                response.TotalPage = totalPage;
            }

            return response;
        }

        public ProvinceResponse SetProvinces(ProvinceRequest request)
        {
            var response = new ProvinceResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.All))
                return response;
            var province = Mapper.FromDataTransferObject(request.Province);

            if (request.Action != "Delete")
            {
                if (!province.Validate())
                {
                    foreach (string error in province.ValidationErrors)
                        response.Message += error + Environment.NewLine;
                    response.Acknowledge = AcknowledgeType.Failure;
                    return response;
                }
            }
            try
            {
                if (request.Action == "Create") { _provinceDao.InsertProvince(province); }
                else if (request.Action == "Update") { _provinceDao.UpdateProvince(province); }
                else
                {
                    var criteria = request.Criteria as ProvinceCriteria;
                    var _province = _provinceDao.GetProvince(criteria.ProvinceCode);
                    _provinceDao.DeleteProvince(_province);
                }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
                return response;
            }

            response.Acknowledge = AcknowledgeType.Success;
            response.RowsAffected = 1;

            return response;
        }

        public AccountingObjectResponse GetAccountingObjects(AccountingObjectRequest request)
        {
            var response = new AccountingObjectResponse(request.RequestId);

            // Validate client tag, access token, and user credentials
            if (!ValidRequest(request, response, Validate.All))
                return response;

            var criteria = request.Criteria as AccountingObjectCriteria;

            if (request.LoadOptions.Contains("AccountingObjects"))
            {
                if (request.LoadOptions.Contains("ByPage"))
                {
                    IEnumerable<AccountingObject> accountingObjects;
                    accountingObjects = _accountingObjectDao.GetAccountingObjectsByPage(criteria.CurrentPage);
                    response.AccountingObjects = accountingObjects.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("ByPageAndBranch"))
                {
                    if (request.LoadOptions.Contains("ByCategory"))
                    {
                        IEnumerable<AccountingObject> accountingObjects;
                        accountingObjects = _accountingObjectDao.GetAccountingObjectsByPageAndBranch(criteria.CurrentPage, request.RestaurantID, criteria.AccountingObjectCategoryId);
                        response.AccountingObjects = accountingObjects.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                    }
                    else
                    {
                        IEnumerable<AccountingObject> accountingObjects;
                        accountingObjects = _accountingObjectDao.GetAccountingObjectsByPageAndBranch(criteria.CurrentPage, request.RestaurantID, criteria.IsCustomer, criteria.IsVendor, criteria.IsEmployee);
                        response.AccountingObjects = accountingObjects.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                    }
                }
                else if (request.LoadOptions.Contains("ActiveByBranch"))
                {
                    IEnumerable<AccountingObject> accountingObjects;
                    accountingObjects = _accountingObjectDao.GetAccountingObjectsActiveByBranch(true, request.RestaurantID, criteria.IsCustomer, criteria.IsVendor, criteria.IsEmployee);
                    response.AccountingObjects = accountingObjects.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else
                {
                    IEnumerable<AccountingObject> accountingObjects;
                    accountingObjects = _accountingObjectDao.GetAccountingObjectsByBranch(request.RestaurantID);
                    response.AccountingObjects = accountingObjects.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
            }

            if (request.LoadOptions.Contains("AccountingObject"))
            {
                if (request.LoadOptions.Contains("ByBranch"))
                {
                    var accountingObject = _accountingObjectDao.GetAccountingObject(request.RestaurantID, criteria.AccountingObjectId);
                    response.AccountingObject = Mapper.ToDataTransferObject(accountingObject);
                }
                //var province = _provinceDao.GetProvince(criteria.ProvinceCode);
                //response.Province = Mapper.ToDataTransferObject(province);
            }

            if (request.LoadOptions.Contains("TotalPage"))
            {
                if (request.LoadOptions.Contains("ByCategory"))
                {
                    var totalPage = _accountingObjectDao.GetTotalPageByCategory(criteria.AccountingObjectCategoryId);
                    response.TotalPage = totalPage;
                }
                else if (request.LoadOptions.Contains("ByBranch"))
                {
                    var totalPage = _accountingObjectDao.GetTotalPageByBranch(request.RestaurantID, criteria.IsCustomer, criteria.IsVendor, criteria.IsEmployee);
                    response.TotalPage = totalPage;
                }
            }

            return response;
        }

        public AccountingObjectResponse SetAccountingObjects(AccountingObjectRequest request)
        {
            var response = new AccountingObjectResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.All))
                return response;
            var accountingObject = Mapper.FromDataTransferObject(request.AccountingObject);

            if (request.Action != "Delete")
            {
                if (!accountingObject.Validate())
                {
                    foreach (string error in accountingObject.ValidationErrors)
                        response.Message += error + Environment.NewLine;
                    response.Acknowledge = AcknowledgeType.Failure;
                    return response;
                }
            }
            try
            {
                if (request.Action == "Create") { _accountingObjectDao.InsertAccountingObject(accountingObject); }
                else if (request.Action == "Update") { _accountingObjectDao.UpdateAccountingObject(accountingObject); }
                else
                {
                    var criteria = request.Criteria as AccountingObjectCriteria;
                    var _accountingObject = _accountingObjectDao.GetAccountingObject(request.RestaurantID, criteria.AccountingObjectId);
                    _accountingObjectDao.DeleteAccountingObject(_accountingObject);
                }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
                return response;
            }

            response.Acknowledge = AcknowledgeType.Success;
            response.RowsAffected = 1;

            return response;
        }

        public InventoryItemCategoryResponse GetInventoryItemCategories(InventoryItemCategoryRequest request)
        {
            var response = new InventoryItemCategoryResponse(request.RequestId);

            // Validate client tag, access token, and user credentials
            if (!ValidRequest(request, response, Validate.All))
                return response;

            var criteria = request.Criteria as InventoryItemCategoryCriteria;

            if (request.LoadOptions.Contains("InventoryItemCategories"))
            {
                IEnumerable<InventoryItemCategory> inventoryItemCategories;
                inventoryItemCategories = _inventoryItemCategoryDao.GetInventoryItemCategories();
                response.InventoryItemCategories = inventoryItemCategories.Select(c => Mapper.ToDataTransferObject(c)).ToList();
            }

            if (request.LoadOptions.Contains("InventoryItemCategory"))
            {
                var inventoryItemCategory = _inventoryItemCategoryDao.GetInventoryItemCategory(criteria.InventoryCategoryID);
                response.InventoryItemCategory = Mapper.ToDataTransferObject(inventoryItemCategory);
            }

            if (request.LoadOptions.Contains("InventoryItemCategoryByBranch"))
            {

                InventoryItemCategory inventoryItemCategory;
                inventoryItemCategory = _inventoryItemCategoryDao.GetInventoryItemCategoryByBranch(request.RestaurantID, criteria.InventoryCategoryID);
                response.InventoryItemCategory = Mapper.ToDataTransferObject(inventoryItemCategory);
            }

            if (request.LoadOptions.Contains("InventoryItemCategoriesByBranch"))
            {
                if (request.LoadOptions.Contains("Active"))
                {
                    IEnumerable<InventoryItemCategory> inventoryItemCategories;
                    inventoryItemCategories = _inventoryItemCategoryDao.GetInventoryItemCategoriesByBranchAndIsActive(request.RestaurantID, criteria.IsMaterial, true);
                    response.InventoryItemCategories = inventoryItemCategories.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("NonActive"))
                {
                    IEnumerable<InventoryItemCategory> inventoryItemCategories;
                    inventoryItemCategories = _inventoryItemCategoryDao.GetInventoryItemCategoriesByBranchAndIsActive(request.RestaurantID, criteria.IsMaterial, false);
                    response.InventoryItemCategories = inventoryItemCategories.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else
                {
                    IEnumerable<InventoryItemCategory> inventoryItemCategories;
                    inventoryItemCategories = _inventoryItemCategoryDao.GetInventoryItemCategoriesByBranch(request.RestaurantID, criteria.IsMaterial);
                    response.InventoryItemCategories = inventoryItemCategories.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
            }

            return response;
        }

        public InventoryItemCategoryResponse SetInventoryItemCategories(InventoryItemCategoryRequest request)
        {
            var response = new InventoryItemCategoryResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.All))
                return response;
            var inventoryItemCategory = Mapper.FromDataTransferObject(request.InventoryItemCategory);

            if (request.Action != "Delete")
            {
                if (!inventoryItemCategory.Validate())
                {
                    foreach (string error in inventoryItemCategory.ValidationErrors)
                        response.Message += error + Environment.NewLine;
                    response.Acknowledge = AcknowledgeType.Failure;
                    return response;
                }
            }
            try
            {
                if (request.Action == "Create") { _inventoryItemCategoryDao.InsertInventoryItemCategory(inventoryItemCategory); }
                else if (request.Action == "Update") { _inventoryItemCategoryDao.UpdateInventoryItemCategory(inventoryItemCategory); }
                else
                {
                    var criteria = request.Criteria as InventoryItemCategoryCriteria;

                    if (_inventoryItemDao.GetCountInventoryItemByCategory(criteria.InventoryCategoryID) > 0)
                    {
                        response.Acknowledge = AcknowledgeType.Failure;
                        response.Message = "Không thể xóa. Loại hàng hóa, vật tư có hàng hóa, vật tư con tương ứng !";
                        return response;
                    }
                    if (_inventoryItemCategoryDao.GetCountInventoryItemCategoryByParentId(criteria.InventoryCategoryID) > 0)
                    {
                        response.Acknowledge = AcknowledgeType.Failure;
                        response.Message = "Không thể xóa. Loại hàng hóa, vật tư có loại hàng hóa, vật tư con tương ứng !";
                        return response;
                    }

                    var _inventoryItemCategory = _inventoryItemCategoryDao.GetInventoryItemCategory(criteria.InventoryCategoryID);
                    _inventoryItemCategoryDao.DeleteInventoryItemCategory(_inventoryItemCategory);
                }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
                return response;
            }

            response.Acknowledge = AcknowledgeType.Success;
            response.RowsAffected = 1;

            return response;
        }

        public StockResponse GetStocks(StockRequest request)
        {
            var response = new StockResponse(request.RequestId);

            // Validate client tag, access token, and user credentials
            if (!ValidRequest(request, response, Validate.All))
                return response;

            var criteria = request.Criteria as StockCriteria;

            if (request.LoadOptions.Contains("Stocks"))
            {
                if (request.LoadOptions.Contains("ByPage"))
                {
                    IEnumerable<Stock> stocks;
                    stocks = _stockDao.GetStocksByPage(criteria.CurrentPage);
                    response.Stocks = stocks.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("ByPageAndBranch"))
                {
                    IEnumerable<Stock> stocks;
                    stocks = _stockDao.GetStocksByPageAndBranch(criteria.CurrentPage, request.RestaurantID);
                    response.Stocks = stocks.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("ByBranch"))
                {
                    IEnumerable<Stock> stocks;
                    stocks = _stockDao.GetStocksByBranch(request.RestaurantID);
                    response.Stocks = stocks.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("ActiveByBranch"))
                {
                    IEnumerable<Stock> stocks;
                    stocks = _stockDao.GetStocksByIsActiveAndBranch(true, request.RestaurantID);
                    response.Stocks = stocks.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("Active"))
                {
                    IEnumerable<Stock> stocks;
                    stocks = _stockDao.GetStocksByIsActive(true);
                    response.Stocks = stocks.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else
                {
                    response.Stocks = null;
                }
            }

            if (request.LoadOptions.Contains("Stock"))
            {
                var stock = _stockDao.GetStock(criteria.StockID);
                response.Stock = Mapper.ToDataTransferObject(stock);
            }

            if (request.LoadOptions.Contains("TotalPage"))
            {
                if (request.LoadOptions.Contains("ByBranch"))
                {
                    var totalPage = _stockDao.GetTotalPageByBranch(request.RestaurantID);
                    response.TotalPage = totalPage;
                }
                else
                {
                    var totalPage = _stockDao.GetTotalPage();
                    response.TotalPage = totalPage;
                }
            }

            return response;
        }

        public StockResponse SetStocks(StockRequest request)
        {
            var response = new StockResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.All))
                return response;
            var stock = Mapper.FromDataTransferObject(request.Stock);

            if (request.Action != "Delete")
            {
                if (!stock.Validate())
                {
                    foreach (string error in stock.ValidationErrors)
                        response.Message += error + Environment.NewLine;
                    response.Acknowledge = AcknowledgeType.Failure;
                    return response;
                }
            }
            try
            {
                if (request.Action == "Create") { _stockDao.InsertStock(stock); }
                else if (request.Action == "Update") { _stockDao.UpdateStock(stock); }
                else
                {
                    var criteria = request.Criteria as StockCriteria;
                    var _stock = _stockDao.GetStock(criteria.StockID);
                    _stockDao.DeleteStock(_stock);
                }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
                return response;
            }

            response.Acknowledge = AcknowledgeType.Success;
            response.RowsAffected = 1;

            return response;
        }

        public InventoryItemResponse GetInventoryItems(InventoryItemRequest request)
        {
            var response = new InventoryItemResponse(request.RequestId);

            // Validate client tag, access token, and user credentials
            if (!ValidRequest(request, response, Validate.All))
                return response;

            var criteria = request.Criteria as InventoryItemCriteria;

            if (request.LoadOptions.Contains("InventoryItems"))
            {
                if (request.LoadOptions.Contains("ByPage"))
                {
                    IEnumerable<InventoryItem> inventoryItems;
                    inventoryItems = _inventoryItemDao.GetInventoryItemsByPage(criteria.CurrentPage, criteria.IsMaterial);
                    response.InventoryItems = inventoryItems.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("ByPageAndCategory"))
                {
                    IEnumerable<InventoryItem> inventoryItems;
                    inventoryItems = _inventoryItemDao.GetInventoryItemsByPageAndCategory(criteria.CurrentPage, criteria.InventoryCategoryID, criteria.IsMaterial);
                    response.InventoryItems = inventoryItems.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("ByPageAndBranch"))
                {
                    IEnumerable<InventoryItem> inventoryItems;
                    inventoryItems = _inventoryItemDao.GetInventoryItemsByPageAndBranch(criteria.CurrentPage, request.RestaurantID, criteria.IsMaterial);
                    response.InventoryItems = inventoryItems.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("Active"))
                {
                    IEnumerable<InventoryItem> inventoryItems;
                    inventoryItems = _inventoryItemDao.GetInventoryItemsActive(criteria.IsMaterial, criteria.IsActive);
                    response.InventoryItems = inventoryItems.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("ActiveByBranch"))
                {
                    IEnumerable<InventoryItem> inventoryItems;
                    inventoryItems = _inventoryItemDao.GetInventoryItemsActive(criteria.IsMaterial, criteria.IsActive, request.RestaurantID);
                    response.InventoryItems = inventoryItems.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
            }

            if (request.LoadOptions.Contains("InventoryItem"))
            {
                var inventoryItem = _inventoryItemDao.GetInventoryItem(criteria.InventoryItemID);
                response.InventoryItem = Mapper.ToDataTransferObject(inventoryItem);
            }

            if (request.LoadOptions.Contains("TotalPage"))
            {
                if (request.LoadOptions.Contains("ByCategory"))
                {
                    var totalPage = _inventoryItemDao.GetTotalPageByCategory(criteria.InventoryCategoryID);
                    response.TotalPage = totalPage;
                }
                else
                {
                    var totalPage = _inventoryItemDao.GetTotalPage(criteria.IsMaterial);
                    response.TotalPage = totalPage;
                }
            }

            return response;
        }

        public InventoryItemResponse SetInventoryItems(InventoryItemRequest request)
        {
            var response = new InventoryItemResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.All))
                return response;
            var inventoryItem = Mapper.FromDataTransferObject(request.InventoryItem);

            if (request.Action != "Delete")
            {
                if (!inventoryItem.Validate())
                {
                    foreach (string error in inventoryItem.ValidationErrors)
                        response.Message += error + Environment.NewLine;
                    response.Acknowledge = AcknowledgeType.Failure;
                    return response;
                }
            }
            try
            {
                if (request.Action == "Create") { _inventoryItemDao.InsertInventoryItem(inventoryItem); }
                else if (request.Action == "Update") { _inventoryItemDao.UpdateInventoryItem(inventoryItem); }
                else
                {
                    var criteria = request.Criteria as InventoryItemCriteria;
                    var _inventoryItem = _inventoryItemDao.GetInventoryItem(criteria.InventoryItemID);
                    _inventoryItemDao.DeleteInventoryItem(_inventoryItem);
                }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
                return response;
            }

            response.Acknowledge = AcknowledgeType.Success;
            response.RowsAffected = 1;

            return response;
        }

        public UnitsResponse GetUnits(UnitsRequest request)
        {
            var response = new UnitsResponse(request.RequestId);

            // Validate client tag, access token, and user credentials
            if (!ValidRequest(request, response, Validate.All))
                return response;

            var criteria = request.Criteria as UnitsCriteria;

            if (request.LoadOptions.Contains("Units"))
            {
                if (request.LoadOptions.Contains("ByPage"))
                {
                    IEnumerable<Unit> units;
                    units = _unitsDao.GetUnitsByPage(criteria.CurrentPage);
                    response.Units = units.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("Active"))
                {
                    IEnumerable<Unit> units;
                    units = _unitsDao.GetUnitsByIsActive(true);
                    response.Units = units.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else
                {
                    IEnumerable<Unit> units;
                    units = _unitsDao.GetUnits();
                    response.Units = units.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
            }

            if (request.LoadOptions.Contains("Unit"))
            {
                var unit = _unitsDao.GetUnit(criteria.UnitID);
                response.Unit = Mapper.ToDataTransferObject(unit);
            }

            if (request.LoadOptions.Contains("TotalPage"))
            {
                var totalPage = _unitsDao.GetTotalPage();
                response.TotalPage = totalPage;
            }

            return response;
        }

        public UnitsResponse SetUnits(UnitsRequest request)
        {
            var response = new UnitsResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.All))
                return response;
            var unit = Mapper.FromDataTransferObject(request.Unit);

            if (request.Action != "Delete")
            {
                if (!unit.Validate())
                {
                    foreach (string error in unit.ValidationErrors)
                        response.Message += error + Environment.NewLine;
                    response.Acknowledge = AcknowledgeType.Failure;
                    return response;
                }
            }
            try
            {
                if (request.Action == "Create") { _unitsDao.InsertUnit(unit); }
                else if (request.Action == "Update") { _unitsDao.UpdateUnit(unit); }
                else
                {
                    var criteria = request.Criteria as UnitsCriteria;
                    var _unit = _unitsDao.GetUnit(criteria.UnitID);
                    _unitsDao.DeleteUnit(_unit);
                }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
                return response;
            }

            response.Acknowledge = AcknowledgeType.Success;
            response.RowsAffected = 1;

            return response;
        }

        public RestaurantResponse GetRestaurants(RestaurantRequest request)
        {
            var response = new RestaurantResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.ClientTag | Validate.AccessToken))
                return response;

            var criteria = request.Criteria as RestaurantCriteria;

            if (request.LoadOptions.Contains("Restaurants"))
            {
                if (request.LoadOptions.Contains("ByPage"))
                {
                    IEnumerable<Restaurant> restaurants;
                    restaurants = _restaurantsDao.GetRestaurantsByPage(criteria.CurrentPage);
                    response.Restaurants = restaurants.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else
                {
                    IEnumerable<Restaurant> restaurants;
                    restaurants = _restaurantsDao.GetRestaurants();
                    response.Restaurants = restaurants.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
            }

            if (request.LoadOptions.Contains("Restaurant"))
            {
                var restaurant = _restaurantsDao.GetRestaurant(criteria.RestaurantId);
                response.Restaurant = Mapper.ToDataTransferObject(restaurant);
            }
            if (request.LoadOptions.Contains("TotalPage"))
            {
                var totalPage = _restaurantsDao.GetTotalPage();
                response.TotalPage = totalPage;
            }

            return response;
        }

        public RestaurantResponse SetRestaurants(RestaurantRequest request)
        {
            var response = new RestaurantResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.All))
                return response;
            var restaurant = Mapper.FromDataTransferObject(request.Restaurant);

            if (request.Action != "Delete")
            {
                if (!restaurant.Validate())
                {
                    foreach (string error in restaurant.ValidationErrors)
                        response.Message += error + Environment.NewLine;
                    response.Acknowledge = AcknowledgeType.Failure;
                    return response;
                }
            }
            try
            {
                if (request.Action == "Create") { _restaurantsDao.InsertRestaurant(restaurant); }
                else if (request.Action == "Update") { _restaurantsDao.UpdateRestaurant(restaurant); }
                else
                {
                    var criteria = request.Criteria as RestaurantCriteria;
                    var _restaurant = _restaurantsDao.GetRestaurant(criteria.RestaurantId);
                    _restaurantsDao.DeleteRestaurant(_restaurant);
                }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
                return response;
            }

            response.Acknowledge = AcknowledgeType.Success;
            response.RowsAffected = 1;

            return response;
        }

        public RestaurantAreaResponse GetRestaurantAreas(RestaurantAreaRequest request)
        {
            var response = new RestaurantAreaResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.ClientTag | Validate.AccessToken))
                return response;

            var criteria = request.Criteria as RestaurantAreaCriteria;

            if (request.LoadOptions.Contains("RestaurantAreas"))
            {
                if (request.LoadOptions.Contains("ByPageAndBranch"))
                {
                    IEnumerable<RestaurantArea> restaurantAreas;
                    restaurantAreas = _restaurantAreaDao.GetRestaurantAreaByPageAndBranch(criteria.CurrentPage, request.RestaurantID);
                    response.RestaurantAreas = restaurantAreas.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("ActiveByBranch"))
                {
                    IEnumerable<RestaurantArea> restaurantAreas;
                    restaurantAreas = _restaurantAreaDao.GetRestaurantAreasActiveByBranch(request.RestaurantID);
                    response.RestaurantAreas = restaurantAreas.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("ByBranch"))
                {
                    IEnumerable<RestaurantArea> restaurantAreas;
                    restaurantAreas = _restaurantAreaDao.GetRestaurantAreasByBranch(request.RestaurantID);
                    response.RestaurantAreas = restaurantAreas.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
            }

            if (request.LoadOptions.Contains("RestaurantArea"))
            {
                var restaurantArea = _restaurantAreaDao.GetRestaurantArea(criteria.RestaurantAreaID);
                response.RestaurantArea = Mapper.ToDataTransferObject(restaurantArea);
            }
            if (request.LoadOptions.Contains("TotalPage"))
            {
                if (request.LoadOptions.Contains("ByBranch"))
                {
                    var totalPage = _restaurantAreaDao.GetTotalPageByBranch(request.RestaurantID);
                    response.TotalPage = totalPage;
                }
            }

            return response;
        }

        public RestaurantAreaResponse SetRestaurantAreas(RestaurantAreaRequest request)
        {
            var response = new RestaurantAreaResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.All))
                return response;
            var restaurantArea = Mapper.FromDataTransferObject(request.RestaurantArea);

            if (request.Action != "Delete")
            {
                if (!restaurantArea.Validate())
                {
                    foreach (string error in restaurantArea.ValidationErrors)
                        response.Message += error + Environment.NewLine;
                    response.Acknowledge = AcknowledgeType.Failure;
                    return response;
                }
            }
            try
            {
                if (request.Action == "Create") { _restaurantAreaDao.InsertRestaurantArea(restaurantArea); }
                else if (request.Action == "Update") { _restaurantAreaDao.UpdateRestaurantArea(restaurantArea); }
                else
                {
                    var criteria = request.Criteria as RestaurantAreaCriteria;
                    var _restaurantArea = _restaurantAreaDao.GetRestaurantArea(criteria.RestaurantAreaID);
                    _restaurantAreaDao.DeleteRestaurantArea(_restaurantArea);
                }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
                return response;
            }

            response.Acknowledge = AcknowledgeType.Success;
            response.RowsAffected = 1;

            return response;
        }

        public RestaurantTableResponse GetRestaurantTables(RestaurantTableRequest request)
        {
            var response = new RestaurantTableResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.ClientTag | Validate.AccessToken))
                return response;

            var criteria = request.Criteria as RestaurantTableCriteria;

            if (request.LoadOptions.Contains("RestaurantTables"))
            {
                if (request.LoadOptions.Contains("ByPageAndBranch"))
                {
                    IEnumerable<RestaurantTable> restaurantAreas;
                    restaurantAreas = _restaurantTableDao.GetRestaurantTablesByPageAndBranch(criteria.CurrentPage, request.RestaurantID);
                    response.RestaurantTables = restaurantAreas.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("ByPageAndArea"))
                {
                    IEnumerable<RestaurantTable> restaurantAreas;
                    restaurantAreas = _restaurantTableDao.GetRestaurantTablesByPageAndArea(criteria.CurrentPage, criteria.RestaurantAreaID);
                    response.RestaurantTables = restaurantAreas.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
            }

            if (request.LoadOptions.Contains("RestaurantTable"))
            {
                var restaurantArea = _restaurantTableDao.GetRestaurantTable(criteria.RestaurantTableID);
                response.RestaurantTable = Mapper.ToDataTransferObject(restaurantArea);
            }
            if (request.LoadOptions.Contains("TotalPage"))
            {
                if (request.LoadOptions.Contains("ByBranch"))
                {
                    var totalPage = _restaurantTableDao.GetTotalPageByBranch(request.RestaurantID);
                    response.TotalPage = totalPage;
                }
            }

            return response;
        }

        public RestaurantTableResponse SetRestaurantTables(RestaurantTableRequest request)
        {
            var response = new RestaurantTableResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.All))
                return response;
            var restaurantArea = Mapper.FromDataTransferObject(request.RestaurantTable);

            if (request.Action != "Delete")
            {
                if (!restaurantArea.Validate())
                {
                    foreach (string error in restaurantArea.ValidationErrors)
                        response.Message += error + Environment.NewLine;
                    response.Acknowledge = AcknowledgeType.Failure;
                    return response;
                }
            }
            try
            {
                if (request.Action == "Create") { _restaurantTableDao.InsertRestaurantTable(restaurantArea); }
                else if (request.Action == "Update") { _restaurantTableDao.UpdateRestaurantTable(restaurantArea); }
                else
                {
                    var criteria = request.Criteria as RestaurantTableCriteria;
                    var _restaurantArea = _restaurantTableDao.GetRestaurantTable(criteria.RestaurantTableID);
                    _restaurantTableDao.DeleteRestaurantTable(_restaurantArea);
                }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
                return response;
            }

            response.Acknowledge = AcknowledgeType.Success;
            response.RowsAffected = 1;

            return response;
        }

        public RestaurantMenuCategoryResponse GetRestaurantMenuCategories(RestaurantMenuCategoryRequest request)
        {
            var response = new RestaurantMenuCategoryResponse(request.RequestId);
            if (!ValidRequest(request, response, Validate.All))
                return response;

            var criteria = request.Criteria as RestaurantMenuCategoryCriteria;

            if (request.LoadOptions.Contains("RestaurantMenuCategories"))
            {
                if (request.LoadOptions.Contains("ByBranch"))
                {
                    IEnumerable<RestaurantMenuCategory> restaurantMenuCategories;
                    restaurantMenuCategories = _restaurantMenuCategoryDao.GetRestaurantMenuCategoriesByBranch(request.RestaurantID);
                    response.RestaurantMenuCategories = restaurantMenuCategories.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("ActiveByBranch"))
                {
                    IEnumerable<RestaurantMenuCategory> restaurantMenuCategories;
                    restaurantMenuCategories = _restaurantMenuCategoryDao.GetRestaurantMenuCategoriesActiveByBranch(true, request.RestaurantID);
                    response.RestaurantMenuCategories = restaurantMenuCategories.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else
                {
                    IEnumerable<RestaurantMenuCategory> restaurantMenuCategories;
                    restaurantMenuCategories = _restaurantMenuCategoryDao.GetRestaurantMenuCategories();
                    response.RestaurantMenuCategories = restaurantMenuCategories.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
            }

            if (request.LoadOptions.Contains("RestaurantMenuCategory"))
            {
                RestaurantMenuCategory restaurantMenuCategory;
                restaurantMenuCategory = _restaurantMenuCategoryDao.GetRestaurantMenuCategory(criteria.MenuCategoryID);
                response.RestaurantMenuCategory = Mapper.ToDataTransferObject(restaurantMenuCategory);
            }

            return response;
        }

        public RestaurantMenuCategoryResponse SetRestaurantMenuCategories(RestaurantMenuCategoryRequest request)
        {
            var response = new RestaurantMenuCategoryResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.All))
                return response;
            var restaurantMenuCategory = Mapper.FromDataTransferObject(request.RestaurantMenuCategory);

            if (request.Action != "Delete")
            {
                if (!restaurantMenuCategory.Validate())
                {
                    foreach (string error in restaurantMenuCategory.ValidationErrors)
                        response.Message += error + Environment.NewLine;
                    response.Acknowledge = AcknowledgeType.Failure;
                    return response;
                }
            }
            try
            {
                if (request.Action == "Create") { _restaurantMenuCategoryDao.InsertRestaurantMenuCategory(restaurantMenuCategory); }
                else if (request.Action == "Update") { _restaurantMenuCategoryDao.UpdateRestaurantMenuCategory(restaurantMenuCategory); }
                else
                {
                    var criteria = request.Criteria as RestaurantMenuCategoryCriteria;
                    var restaurantMenus = _restaurantMenuDao.GetRestaurantMenusByCategoryId(criteria.MenuCategoryID);

                    if (_restaurantMenuCategoryDao.GetCountRestaurantMenuCategoryByParentId(criteria.MenuCategoryID) > 0)
                    {
                        response.Acknowledge = AcknowledgeType.Failure;
                        response.Message = "Không thể xóa. Loại món ăn có loại món ăn tương ứng !";
                        return response;
                    }
                    if (restaurantMenus != null && restaurantMenus.Count > 0)
                    {
                        response.Acknowledge = AcknowledgeType.Failure;
                        response.Message = "Không thể xóa. Loại món ăn có món ăn tương ứng !";
                        return response;
                    }

                    var _restaurantMenuCategory = _restaurantMenuCategoryDao.GetRestaurantMenuCategory(criteria.MenuCategoryID);
                    _restaurantMenuCategoryDao.DeleteRestaurantMenuCategory(_restaurantMenuCategory);
                }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
                return response;
            }

            response.Acknowledge = AcknowledgeType.Success;
            response.RowsAffected = 1;

            return response;
        }

        public RestaurantMenuResponse GetRestaurantMenus(RestaurantMenuRequest request)
        {
            var response = new RestaurantMenuResponse(request.RequestId);

            // Validate client tag, access token, and user credentials
            if (!ValidRequest(request, response, Validate.All))
                return response;

            var criteria = request.Criteria as RestaurantMenuCriteria;

            if (request.LoadOptions.Contains("RestaurantMenus"))
            {
                if (request.LoadOptions.Contains("ByPageAndCategory"))
                {
                    IEnumerable<RestaurantMenu> restaurantMenus;
                    restaurantMenus = _restaurantMenuDao.GetRestaurantMenusPagedByCategory(criteria.CurrentPage, criteria.MenuCategoryID);
                    response.RestaurantMenus = restaurantMenus.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("ByPageAndBranch"))
                {
                    IEnumerable<RestaurantMenu> restaurantMenus;
                    restaurantMenus = _restaurantMenuDao.GetRestaurantMenusPagedByBranch(criteria.CurrentPage, request.RestaurantID);
                    response.RestaurantMenus = restaurantMenus.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("ActiveByBranch"))
                {
                    IEnumerable<RestaurantMenu> restaurantMenus;
                    restaurantMenus = _restaurantMenuDao.GetRestaurantMenusActiveByBranch(request.RestaurantID, true);
                    response.RestaurantMenus = restaurantMenus.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
            }

            if (request.LoadOptions.Contains("RestaurantMenu"))
            {
                var restaurantMenu = _restaurantMenuDao.GetRestaurantMenu(criteria.MenuID);
                restaurantMenu.MenuImage = null;
                response.RestaurantMenu = Mapper.ToDataTransferObject(restaurantMenu);

                if (request.LoadOptions.Contains("RestaurantMenuNorms"))
                {
                    var restaurantMenuNorms = _restaurantMenuNormDao.GetRestaurantMenuNormsByMenuId(criteria.MenuID);
                    response.RestaurantMenu.RestaurantMenuNorms = restaurantMenuNorms.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
            }

            if (request.LoadOptions.Contains("TotalPage"))
            {
                if (request.LoadOptions.Contains("ByCategory"))
                {
                    var totalPage = _restaurantMenuDao.GetTotalPageByCategory(criteria.MenuCategoryID);
                    response.TotalPage = totalPage;
                }
                else
                {
                    var totalPage = _restaurantMenuDao.GetTotalPageByBranch(request.RestaurantID);
                    response.TotalPage = totalPage;
                }
            }

            return response;
        }

        public RestaurantMenuResponse SetRestaurantMenus(RestaurantMenuRequest request)
        {
            var response = new RestaurantMenuResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.All))
                return response;
            var restaurantMenu = Mapper.FromDataTransferObject(request.RestaurantMenu);

            if (request.Action != "Delete")
            {
                if (!restaurantMenu.Validate())
                {
                    foreach (string error in restaurantMenu.ValidationErrors)
                        response.Message += error + Environment.NewLine;
                    response.Acknowledge = AcknowledgeType.Failure;
                    return response;
                }
            }
            try
            {
                if (request.Action == "Create") { _restaurantMenuDao.InsertRestaurantMenu(restaurantMenu); }
                else if (request.Action == "Update") { _restaurantMenuDao.UpdateRestaurantMenu(restaurantMenu); }
                else
                {
                    var criteria = request.Criteria as RestaurantMenuCriteria;
                    var _restaurantMenu = _restaurantMenuDao.GetRestaurantMenu(criteria.MenuID);
                    _restaurantMenuDao.DeleteRestaurantMenu(_restaurantMenu);
                }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
                return response;
            }

            response.Acknowledge = AcknowledgeType.Success;
            response.RowsAffected = 1;

            return response;
        }

        public RestaurantMenuNormResponse GetRestaurantMenuNorms(RestaurantMenuNormRequest request)
        {
            var response = new RestaurantMenuNormResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.All))
                return response;

            var criteria = request.Criteria as RestaurantMenuNormCriteria;

            if (request.LoadOptions.Contains("RestaurantMenuNorms"))
            {
                if (request.LoadOptions.Contains("ByPageAndBranch"))
                {
                    IEnumerable<RestaurantMenuNorm> restaurantMenuNorms;
                    restaurantMenuNorms = _restaurantMenuNormDao.GetRestaurantMenuNormsPagedByBranch(request.RestaurantID, criteria.CurrentPage);
                    response.RestaurantMenuNorms = restaurantMenuNorms.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
            }

            if (request.LoadOptions.Contains("RestaurantMenuNorm"))
            {
                RestaurantMenuNorm restaurantMenuNorm;
                restaurantMenuNorm = _restaurantMenuNormDao.GetRestaurantMenuNorm(criteria.MenuNormID);
                response.RestaurantMenuNorm = Mapper.ToDataTransferObject(restaurantMenuNorm);

                if (request.LoadOptions.Contains("RestaurantMenuNormDetails"))
                {
                    IEnumerable<RestaurantMenuNormDetail> restaurantMenuNormDetails;
                    restaurantMenuNormDetails = _restaurantMenuNormDetailDao.GetRestaurantMenuNormDetailsByCategory(criteria.MenuNormID);
                    response.RestaurantMenuNormDetails = restaurantMenuNormDetails.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
            }

            if (request.LoadOptions.Contains("TotalPage"))
            {
                if (request.LoadOptions.Contains("ByBranch"))
                {
                    var totalPage = _restaurantMenuNormDao.GetTotalPageByBranch(request.RestaurantID);
                    response.TotalPage = totalPage;
                }
            }

            return response;
        }

        public RestaurantMenuNormResponse SetRestaurantMenuNorms(RestaurantMenuNormRequest request)
        {
            var response = new RestaurantMenuNormResponse(request.RequestId);
            var criteria = request.Criteria as RestaurantMenuNormCriteria;

            if (!ValidRequest(request, response, Validate.All))
                return response;
            var restaurantMenuNorm = Mapper.FromDataTransferObject(request.RestaurantMenuNorm);

            if (request.Action != "Delete")
            {
                if (!restaurantMenuNorm.Validate())
                {
                    foreach (string error in restaurantMenuNorm.ValidationErrors)
                        response.Message += error + Environment.NewLine;
                    response.Acknowledge = AcknowledgeType.Failure;
                    return response;
                }
            }
            try
            {
                if (request.Action == "Create")
                {
                    if (request.LoadOptions.Contains("RestaurantMenuNormDetails"))
                    {
                        using (TransactionScope scope = new TransactionScope())
                        {
                            _restaurantMenuNormDao.InsertRestaurantMenuNorm(restaurantMenuNorm);
                            if (criteria.RestaurantMenuNormDetails != null && criteria.RestaurantMenuNormDetails.Count > 0)
                            {
                                var restaurantMenuNormDetails = criteria.RestaurantMenuNormDetails.Select(c => Mapper.FromDataTransferObject(c));
                                foreach (var item in restaurantMenuNormDetails)
                                {
                                    if (!item.Validate())
                                    {
                                        foreach (string error in restaurantMenuNorm.ValidationErrors)
                                            response.Message += error + Environment.NewLine;
                                        response.Acknowledge = AcknowledgeType.Failure;
                                        return response;
                                    }
                                    _restaurantMenuNormDetailDao.InsertRestaurantMenuNormDetail(item);
                                }
                            }
                            scope.Complete();
                        }
                    }
                    else { _restaurantMenuNormDao.InsertRestaurantMenuNorm(restaurantMenuNorm); }
                }
                else if (request.Action == "Update")
                {
                    if (request.LoadOptions.Contains("RestaurantMenuNormDetails"))
                    {
                        using (TransactionScope scope = new TransactionScope())
                        {
                            _restaurantMenuNormDao.UpdateRestaurantMenuNorm(restaurantMenuNorm);
                            _restaurantMenuNormDetailDao.DeleteRestaurantMenuNormDetailByCategory(restaurantMenuNorm.MenuNormID);
                            if (criteria.RestaurantMenuNormDetails != null && criteria.RestaurantMenuNormDetails.Count > 0)
                            {
                                var restaurantMenuNormDetails = criteria.RestaurantMenuNormDetails.Select(c => Mapper.FromDataTransferObject(c));
                                foreach (var item in restaurantMenuNormDetails)
                                {
                                    if (!item.Validate())
                                    {
                                        foreach (string error in restaurantMenuNorm.ValidationErrors)
                                            response.Message += error + Environment.NewLine;
                                        response.Acknowledge = AcknowledgeType.Failure;
                                        return response;
                                    }
                                    _restaurantMenuNormDetailDao.InsertRestaurantMenuNormDetail(item);
                                }
                            }
                            scope.Complete();
                        }
                    }
                    else { _restaurantMenuNormDao.UpdateRestaurantMenuNorm(restaurantMenuNorm); }
                }
                else
                {
                    if (request.LoadOptions.Contains("RestaurantMenuNormDetails"))
                    {
                        using (TransactionScope scope = new TransactionScope())
                        {
                            var _restaurantMenuNorm = _restaurantMenuNormDao.GetRestaurantMenuNorm(criteria.MenuNormID);
                            _restaurantMenuNormDetailDao.DeleteRestaurantMenuNormDetailByCategory(criteria.MenuNormID);
                            _restaurantMenuNormDao.DeleteRestaurantMenuNorm(_restaurantMenuNorm);

                            scope.Complete();
                        }
                    }
                    else
                    {
                        var _restaurantMenuNorm = _restaurantMenuNormDao.GetRestaurantMenuNorm(criteria.MenuNormID);
                        _restaurantMenuNormDao.DeleteRestaurantMenuNorm(_restaurantMenuNorm);
                    }
                }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
                return response;
            }

            response.Acknowledge = AcknowledgeType.Success;
            response.RowsAffected = 1;

            return response;
        }

        public RestaurantMenuNormDetailResponse GetRestaurantMenuNormDetails(RestaurantMenuNormDetailRequest request)
        {
            var response = new RestaurantMenuNormDetailResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.All))
                return response;

            var criteria = request.Criteria as RestaurantMenuNormDetailCriteria;

            if (request.LoadOptions.Contains("RestaurantMenuNormDetails"))
            {
                if (request.LoadOptions.Contains("ByCategory"))
                {
                    IEnumerable<RestaurantMenuNormDetail> restaurantMenuNormDetails;
                    restaurantMenuNormDetails = _restaurantMenuNormDetailDao.GetRestaurantMenuNormDetailsByCategory(criteria.MenuNormID);
                    response.RestaurantMenuNormDetails = restaurantMenuNormDetails.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
            }

            return response;
        }

        public CurrencyResponse GetCurrencies(CurrencyRequest request)
        {
            var response = new CurrencyResponse(request.RequestId);

            // Validate client tag, access token, and user credentials
            if (!ValidRequest(request, response, Validate.All))
                return response;

            var criteria = request.Criteria as CurrencyCriteria;

            if (request.LoadOptions.Contains("Currencies"))
            {
                if (request.LoadOptions.Contains("ByPage"))
                {
                    IEnumerable<Currency> Currencys;
                    Currencys = _currencyDao.GetCurrenciesByPage(criteria.CurrentPage);
                    response.Currencies = Currencys.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("Active"))
                {
                    IEnumerable<Currency> Currencys;
                    Currencys = _currencyDao.GetCurrenciesByIsActive(true);
                    response.Currencies = Currencys.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else
                {
                    IEnumerable<Currency> Currencys;
                    Currencys = _currencyDao.GetCurrencies();
                    response.Currencies = Currencys.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
            }

            if (request.LoadOptions.Contains("Currency"))
            {
                var Currency = _currencyDao.GetCurrency(criteria.CurrencyID);
                response.Currency = Mapper.ToDataTransferObject(Currency);
            }

            if (request.LoadOptions.Contains("TotalPage"))
            {
                var totalPage = _currencyDao.GetTotalPage();
                response.TotalPage = totalPage;
            }

            return response;
        }

        public CurrencyResponse SetCurrencies(CurrencyRequest request)
        {
            var response = new CurrencyResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.All))
                return response;
            var currency = Mapper.FromDataTransferObject(request.Currency);

            if (request.Action != "Delete")
            {
                if (!currency.Validate())
                {
                    foreach (string error in currency.ValidationErrors)
                        response.Message += error + Environment.NewLine;
                    response.Acknowledge = AcknowledgeType.Failure;
                    return response;
                }
            }
            try
            {
                if (request.Action == "Create") { _currencyDao.InsertCurrency(currency); }
                else if (request.Action == "Update") { _currencyDao.UpdateCurrency(currency); }
                else
                {
                    var criteria = request.Criteria as CurrencyCriteria;
                    var _currency = _currencyDao.GetCurrency(criteria.CurrencyID);
                    _currencyDao.DeleteCurrency(_currency);
                }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
                return response;
            }

            response.Acknowledge = AcknowledgeType.Success;
            response.RowsAffected = 1;

            return response;
        }

        public DepartmentResponse GetDepartments(DepartmentRequest request)
        {
            var response = new DepartmentResponse(request.RequestId);

            // Validate client tag, access token, and user credentials
            if (!ValidRequest(request, response, Validate.All))
                return response;

            var criteria = request.Criteria as DepartmentCriteria;

            if (request.LoadOptions.Contains("Departments"))
            {
                if (request.LoadOptions.Contains("ByBranch"))
                {
                    IEnumerable<Department> departments;
                    departments = _departmentDao.GetDepartmentsByBranch(request.RestaurantID);
                    response.Departments = departments.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("ActiveByBranch"))
                {
                    IEnumerable<Department> departments;
                    departments = _departmentDao.GetDepartmentsActiveByBranch(criteria.IsActive, request.RestaurantID);
                    response.Departments = departments.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else
                {
                    IEnumerable<Department> departments;
                    departments = _departmentDao.GetDepartments();
                    response.Departments = departments.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
            }

            if (request.LoadOptions.Contains("Department"))
            {
                var department = _departmentDao.GetDepartment(criteria.DepartmentID);
                response.Department = Mapper.ToDataTransferObject(department);
            }

            return response;
        }

        public DepartmentResponse SetDepartments(DepartmentRequest request)
        {
            var response = new DepartmentResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.All))
                return response;
            var department = Mapper.FromDataTransferObject(request.Department);

            if (request.Action != "Delete")
            {
                if (!department.Validate())
                {
                    foreach (string error in department.ValidationErrors)
                        response.Message += error + Environment.NewLine;
                    response.Acknowledge = AcknowledgeType.Failure;
                    return response;
                }
            }
            try
            {
                if (request.Action == "Create") { _departmentDao.InsertDepartment(department); }
                else if (request.Action == "Update") { _departmentDao.UpdateDepartment(department); }
                else
                {
                    var criteria = request.Criteria as DepartmentCriteria;
                    var _department = _departmentDao.GetDepartment(criteria.DepartmentID);
                    //kiem tra xem co con nao khong
                    if (_departmentDao.GetCountDepartmentByParentId(criteria.DepartmentID) > 0)
                    {
                        response.Acknowledge = AcknowledgeType.Failure;
                        response.Message = "Không thể xóa. Phòng ban có phong ban con tương ứng !";
                        return response;
                    }
                    _departmentDao.DeleteDepartment(_department);
                }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
                return response;
            }

            response.Acknowledge = AcknowledgeType.Success;
            response.RowsAffected = 1;

            return response;
        }

        public TimeSheetSignResponse GetTimeSheetSigns(TimeSheetSignRequest request)
        {
            var response = new TimeSheetSignResponse(request.RequestId);

            // Validate client tag, access token, and user credentials
            if (!ValidRequest(request, response, Validate.All))
                return response;

            var criteria = request.Criteria as TimeSheetSignCriteria;

            if (request.LoadOptions.Contains("TimeSheetSigns"))
            {
                if (request.LoadOptions.Contains("Active"))
                {
                    IEnumerable<TimeSheetSign> timeSheetSigns;
                    timeSheetSigns = _timeSheetSignDao.GetTimeSheetSignsActive(true);
                    response.TimeSheetSigns = timeSheetSigns.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("ByPage"))
                {
                    IEnumerable<TimeSheetSign> timeSheetSigns;
                    timeSheetSigns = _timeSheetSignDao.GetTimeSheetSignPaged(criteria.CurrentPage);
                    response.TimeSheetSigns = timeSheetSigns.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else
                {
                    IEnumerable<TimeSheetSign> timeSheetSigns;
                    timeSheetSigns = _timeSheetSignDao.GetTimeSheetSigns();
                    response.TimeSheetSigns = timeSheetSigns.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
            }

            if (request.LoadOptions.Contains("TimeSheetSign"))
            {
                var timeSheetSign = _timeSheetSignDao.GetTimeSheetSign(criteria.TimeSheetSignID);
                response.TimeSheetSign = Mapper.ToDataTransferObject(timeSheetSign);
            }

            if (request.LoadOptions.Contains("TotalPage"))
            {
                var totalPage = _timeSheetSignDao.GetTotalPage();
                response.TotalPage = totalPage;
            }

            return response;
        }

        public TimeSheetSignResponse SetTimeSheetSigns(TimeSheetSignRequest request)
        {
            var response = new TimeSheetSignResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.All))
                return response;
            var timeSheetSign = Mapper.FromDataTransferObject(request.TimeSheetSign);

            if (request.Action != "Delete")
            {
                if (!timeSheetSign.Validate())
                {
                    foreach (string error in timeSheetSign.ValidationErrors)
                        response.Message += error + Environment.NewLine;
                    response.Acknowledge = AcknowledgeType.Failure;
                    return response;
                }
            }
            try
            {
                if (request.Action == "Create") { _timeSheetSignDao.InsertTimeSheetSign(timeSheetSign); }
                else if (request.Action == "Update") { _timeSheetSignDao.UpdateTimeSheetSign(timeSheetSign); }
                else
                {
                    var criteria = request.Criteria as TimeSheetSignCriteria;
                    var _timeSheetSign = _timeSheetSignDao.GetTimeSheetSign(criteria.TimeSheetSignID);
                    _timeSheetSignDao.DeleteTimeSheetSign(_timeSheetSign);
                }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
                return response;
            }

            response.Acknowledge = AcknowledgeType.Success;
            response.RowsAffected = 1;

            return response;
        }

        public ShipMethodResponse GetShipMethods(ShipMethodRequest request)
        {
            var response = new ShipMethodResponse(request.RequestId);

            // Validate client tag, access token, and user credentials
            if (!ValidRequest(request, response, Validate.All))
                return response;

            var criteria = request.Criteria as ShipMethodCriteria;

            if (request.LoadOptions.Contains("ShipMethods"))
            {
                if (request.LoadOptions.Contains("Active"))
                {
                    IEnumerable<ShipMethod> shipMethods;
                    shipMethods = _shipMethodDao.GetShipMethodsActive(true);
                    response.ShipMethods = shipMethods.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else if (request.LoadOptions.Contains("ByPage"))
                {
                    IEnumerable<ShipMethod> shipMethods;
                    shipMethods = _shipMethodDao.GetShipMethodsPaged(criteria.CurrentPage);
                    response.ShipMethods = shipMethods.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
                else
                {
                    IEnumerable<ShipMethod> shipMethods;
                    shipMethods = _shipMethodDao.GetShipMethods();
                    response.ShipMethods = shipMethods.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
            }

            if (request.LoadOptions.Contains("ShipMethod"))
            {
                var shipMethod = _shipMethodDao.GetShipMethod(criteria.ShipMethodID);
                response.ShipMethod = Mapper.ToDataTransferObject(shipMethod);
            }

            if (request.LoadOptions.Contains("TotalPage"))
            {
                var totalPage = _shipMethodDao.GetTotalPage();
                response.TotalPage = totalPage;
            }

            return response;
        }

        public ShipMethodResponse SetShipMethods(ShipMethodRequest request)
        {
            var response = new ShipMethodResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.All))
                return response;
            var shipMethod = Mapper.FromDataTransferObject(request.ShipMethod);

            if (request.Action != "Delete")
            {
                if (!shipMethod.Validate())
                {
                    foreach (string error in shipMethod.ValidationErrors)
                        response.Message += error + Environment.NewLine;
                    response.Acknowledge = AcknowledgeType.Failure;
                    return response;
                }
            }
            try
            {
                if (request.Action == "Create") { _shipMethodDao.InsertShipMethod(shipMethod); }
                else if (request.Action == "Update") { _shipMethodDao.UpdateShipMethod(shipMethod); }
                else
                {
                    var criteria = request.Criteria as ShipMethodCriteria;
                    var _shipMethod = _shipMethodDao.GetShipMethod(criteria.ShipMethodID);
                    _shipMethodDao.DeleteShipMethod(_shipMethod);
                }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
                return response;
            }

            response.Acknowledge = AcknowledgeType.Success;
            response.RowsAffected = 1;

            return response;
        }

        public AutoIDResponse GetAutoIDs(AutoIDRequest request)
        {
            var response = new AutoIDResponse(request.RequestId);

            // Validate client tag, access token, and user credentials
            if (!ValidRequest(request, response, Validate.All))
                return response;

            var criteria = request.Criteria as AutoIDCriteria;

            if (request.LoadOptions.Contains("AutoID"))
            {
                if (request.LoadOptions.Contains("RefTypeId"))
                {
                    var autoId = _autoIdDao.GetAutoIDRefTypeByBranch(criteria.RefTypeID, request.RestaurantID);
                    response.AutoID = Mapper.ToDataTransferObject(autoId);
                }
            }

            return response;
        }

        public AutoIDResponse SetAutoIDs(AutoIDRequest request)
        {
            var response = new AutoIDResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.All))
                return response;
            var autoId = Mapper.FromDataTransferObject(request.AutoID);

            if (request.Action != "Delete")
            {
                if (!autoId.Validate())
                {
                    foreach (string error in autoId.ValidationErrors)
                        response.Message += error + Environment.NewLine;
                    response.Acknowledge = AcknowledgeType.Failure;
                    return response;
                }
            }
            try
            {
                if (request.Action == "Update") { _autoIdDao.UpdateAutoId(autoId); }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
                return response;
            }

            response.Acknowledge = AcknowledgeType.Success;
            response.RowsAffected = 1;

            return response;
        }

        public InwardOutwardResponse GetInwardOutwards(InwardOutwardRequest request)
        {
            var response = new InwardOutwardResponse(request.RequestId);

            if (!ValidRequest(request, response, Validate.All))
                return response;

            var criteria = request.Criteria as InwardOutwardCriteria;

            if (request.LoadOptions.Contains("InwardOutwards"))
            {
                if (request.LoadOptions.Contains("ByPageAndBranch"))
                {
                    if (request.LoadOptions.Contains("RefType"))
                    {
                        IEnumerable<InwardOutward> inwardOutwards;
                        inwardOutwards = _inwardOutwardDao.GetInwardOutwardsPagedByBranch(criteria.RefType, request.RestaurantID, criteria.CurrentPage, criteria.IsMaterial);
                        response.InwardOutwards = inwardOutwards.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                    }
                }
            }

            if (request.LoadOptions.Contains("InwardOutward"))
            {
                InwardOutward inwardOutward;
                inwardOutward = _inwardOutwardDao.GetInwardOutward(criteria.RefID);
                response.InwardOutward = Mapper.ToDataTransferObject(inwardOutward);

                if (request.LoadOptions.Contains("InwardOutwardDetails"))
                {
                    IEnumerable<InwardOutwardDetail> inwardOutwardDetails;
                    inwardOutwardDetails = _inwardOutwardDetailDao.GetInwardOutwardDetailsByRefId(criteria.RefID);
                    response.InwardOutwardDetails = inwardOutwardDetails.Select(c => Mapper.ToDataTransferObject(c)).ToList();
                }
            }

            if (request.LoadOptions.Contains("TotalPage"))
            {
                if (request.LoadOptions.Contains("ByBranch"))
                {
                    if (request.LoadOptions.Contains("RefType"))
                    {
                        var totalPage = _inwardOutwardDao.GetTotalPageByBranch(criteria.RefType, request.RestaurantID, criteria.IsMaterial);
                        response.TotalPage = totalPage;
                    }
                }
            }

            return response;
        }

        public InwardOutwardResponse SetInwardOutwards(InwardOutwardRequest request)
        {
            var response = new InwardOutwardResponse(request.RequestId);
            var criteria = request.Criteria as InwardOutwardCriteria;

            if (!ValidRequest(request, response, Validate.All))
                return response;
            var inwardOutward = Mapper.FromDataTransferObject(request.InwardOutward);

            if (request.Action != "Delete")
            {
                if (!inwardOutward.Validate())
                {
                    foreach (string error in inwardOutward.ValidationErrors)
                        response.Message += error + Environment.NewLine;
                    response.Acknowledge = AcknowledgeType.Failure;
                    return response;
                }
            }
            try
            {
                if (request.Action == "Create")
                {
                    if (request.LoadOptions.Contains("InwardOutwardDetails"))
                    {
                        using (TransactionScope scope = new TransactionScope())
                        {
                            _inwardOutwardDao.InsertInwardOutward(inwardOutward);
                            if (criteria.InwardOutwardDetails != null && criteria.InwardOutwardDetails.Count > 0)
                            {
                                //insert details
                                var inwardOutwardDetails = criteria.InwardOutwardDetails.Select(c => Mapper.FromDataTransferObject(c));
                                foreach (var inwardOutwardDetail in inwardOutwardDetails)
                                {
                                    if (!inwardOutwardDetail.Validate())
                                    {
                                        foreach (string error in inwardOutwardDetail.ValidationErrors)
                                            response.Message += error + Environment.NewLine;
                                        response.Acknowledge = AcknowledgeType.Failure;
                                        return response;
                                    }
                                    _inwardOutwardDetailDao.InsertInwardOutwardDetail(inwardOutwardDetail);
                                }
                            }

                            if (criteria.InventoryLedgers != null && criteria.InventoryLedgers.Count > 0)
                            {
                                //insert so cai vat tu
                                var inventoryLedgers = criteria.InventoryLedgers.Select(c => Mapper.FromDataTransferObject(c));
                                foreach (var inventoryLedger in inventoryLedgers)
                                {
                                    if (!inventoryLedger.Validate())
                                    {
                                        foreach (string error in inventoryLedger.ValidationErrors)
                                            response.Message += error + Environment.NewLine;
                                        response.Acknowledge = AcknowledgeType.Failure;
                                        return response;
                                    }
                                    _inventoryLedgerDao.InsertInventoryLedger(inventoryLedger);
                                }
                            }

                            if (criteria.GeneralLedgers != null && criteria.GeneralLedgers.Count > 0)
                            {
                                //insert so cai ke toan
                                var generalLedgers = criteria.GeneralLedgers.Select(c => Mapper.FromDataTransferObject(c));
                                foreach (var generalLedger in generalLedgers)
                                {
                                    if (!generalLedger.Validate())
                                    {
                                        foreach (string error in generalLedger.ValidationErrors)
                                            response.Message += error + Environment.NewLine;
                                        response.Acknowledge = AcknowledgeType.Failure;
                                        return response;
                                    }
                                    _generalLedgerDao.InsertGeneralLedger(generalLedger);
                                }
                            }
                            //thay doi autoID
                            var autoId = _autoIdDao.GetAutoIDRefTypeByBranch(criteria.RefType, request.RestaurantID);
                            autoId.Value += 1;
                            _autoIdDao.UpdateAutoId(autoId);
                            scope.Complete();
                        }
                    }
                    else { _inwardOutwardDao.InsertInwardOutward(inwardOutward); }
                }
                else if (request.Action == "Update")
                {
                    if (request.LoadOptions.Contains("InwardOutwardDetails"))
                    {
                        using (TransactionScope scope = new TransactionScope())
                        {
                            //delete so cai 
                            foreach (var generalLedger in criteria.GeneralLedgers.Select(c => Mapper.FromDataTransferObject(c)))
                            {
                                if (generalLedger != null)
                                    _generalLedgerDao.DeleteGeneralLedgerByRefId(generalLedger);
                            }
                            //delete so vat tu
                            foreach (var inventoryLedger in criteria.InventoryLedgers.Select(c => Mapper.FromDataTransferObject(c)))
                            {
                                if (inventoryLedger != null)
                                    _inventoryLedgerDao.DeleteInventoryLedgerByRefId(inventoryLedger);
                            }
                            //delete nhap kho chi tiet
                            foreach (var inwardOutwardDetail in criteria.InwardOutwardDetails.Select(c => Mapper.FromDataTransferObject(c)))
                            {
                                if (inwardOutwardDetail != null)
                                    _inwardOutwardDetailDao.DeleteInwardOutwardDetailByRefId(inwardOutwardDetail);
                            }
                            //update nhap kho
                            _inwardOutwardDao.UpdateInwardOutward(inwardOutward);
                            if (criteria.InwardOutwardDetails != null && criteria.InwardOutwardDetails.Count > 0)
                            {
                                //insert details
                                var inwardOutwardDetails = criteria.InwardOutwardDetails.Select(c => Mapper.FromDataTransferObject(c));
                                foreach (var inwardOutwardDetail in inwardOutwardDetails)
                                {
                                    if (!inwardOutwardDetail.Validate())
                                    {
                                        foreach (string error in inwardOutwardDetail.ValidationErrors)
                                            response.Message += error + Environment.NewLine;
                                        response.Acknowledge = AcknowledgeType.Failure;
                                        return response;
                                    }
                                    _inwardOutwardDetailDao.InsertInwardOutwardDetail(inwardOutwardDetail);
                                }
                            }

                            if (criteria.InventoryLedgers != null && criteria.InventoryLedgers.Count > 0)
                            {
                                //insert so cai vat tu
                                var inventoryLedgers = criteria.InventoryLedgers.Select(c => Mapper.FromDataTransferObject(c));
                                foreach (var inventoryLedger in inventoryLedgers)
                                {
                                    if (!inventoryLedger.Validate())
                                    {
                                        foreach (string error in inventoryLedger.ValidationErrors)
                                            response.Message += error + Environment.NewLine;
                                        response.Acknowledge = AcknowledgeType.Failure;
                                        return response;
                                    }
                                    _inventoryLedgerDao.InsertInventoryLedger(inventoryLedger);
                                }
                            }

                            if (criteria.GeneralLedgers != null && criteria.GeneralLedgers.Count > 0)
                            {
                                //insert so cai ke toan
                                var generalLedgers = criteria.GeneralLedgers.Select(c => Mapper.FromDataTransferObject(c));
                                foreach (var generalLedger in generalLedgers)
                                {
                                    if (!generalLedger.Validate())
                                    {
                                        foreach (string error in generalLedger.ValidationErrors)
                                            response.Message += error + Environment.NewLine;
                                        response.Acknowledge = AcknowledgeType.Failure;
                                        return response;
                                    }
                                    _generalLedgerDao.InsertGeneralLedger(generalLedger);
                                }
                            }
                            scope.Complete();
                        }
                    }
                }
                else if (request.Action == "Delete")
                {
                    using (TransactionScope scope = new TransactionScope())
                    {
                        //delete so cai 
                        foreach (var generalLedger in criteria.GeneralLedgers.Select(c => Mapper.FromDataTransferObject(c)))
                        {
                            if (generalLedger != null)
                                _generalLedgerDao.DeleteGeneralLedgerByRefId(generalLedger);
                        }
                        //delete so vat tu
                        foreach (var inventoryLedger in criteria.InventoryLedgers.Select(c => Mapper.FromDataTransferObject(c)))
                        {
                            if (inventoryLedger != null)
                                _inventoryLedgerDao.DeleteInventoryLedgerByRefId(inventoryLedger);
                        }
                        //delete nhap kho chi tiet
                        foreach (var inwardOutwardDetail in criteria.InwardOutwardDetails.Select(c => Mapper.FromDataTransferObject(c)))
                        {
                            if (inwardOutwardDetail != null)
                                _inwardOutwardDetailDao.DeleteInwardOutwardDetailByRefId(inwardOutwardDetail);
                        }
                        _inwardOutwardDao.DeleteInwardOutward(inwardOutward);
                        scope.Complete();
                    }
                }
            }
            catch (Exception ex)
            {
                response.Acknowledge = AcknowledgeType.Failure;
                response.Message = ex.Message;
                return response;
            }

            response.Acknowledge = AcknowledgeType.Success;
            response.RowsAffected = 1;
            return response;
        }

        private bool ValidRequest(RequestBase request, ResponseBase response, Validate validate)
        {
            // Validate Client Tag. 
            // Hardcoded here. In production this should query a 'client' table in a database.
            if ((Validate.ClientTag & validate) == Validate.ClientTag)
            {
                if (request.ClientTag != "RSM123")
                {
                    response.Acknowledge = AcknowledgeType.Failure;
                    response.Message = "Client tag không hợp lệ !";
                    return false;
                }
            }


            // Validate access token
            if ((Validate.AccessToken & validate) == Validate.AccessToken)
            {
                if (request.AccessToken != _accessToken)
                {
                    response.Acknowledge = AcknowledgeType.Failure;
                    response.Message = "AccessToken không hợp lệ hoặc hết hạn. Gọi phương thức GetToken()";
                    return false;
                }
            }

            // Validate user credentials
            if ((Validate.UserCredentials & validate) == Validate.UserCredentials)
            {
                if (_userName == null)
                {
                    response.Acknowledge = AcknowledgeType.Failure;
                    response.Message = "Bạn có thể đăng nhập và cung cấp các thông tin người dùng trước khi truy cập những phương pháp này.";
                    return false;
                }
            }

            //Validate access RestaurantID
            if ((Validate.RestaurantId & validate) == Validate.RestaurantId)
            {
                if (request.RestaurantID != _restaurantId)
                {
                    response.Acknowledge = AcknowledgeType.Failure;
                    response.Message = "Mã số nhà hàng không hợp lệ";
                    return false;
                }
            }

            return true;
        }

        [Flags]
        private enum Validate
        {
            ClientTag = 0x0001,
            AccessToken = 0x0002,
            UserCredentials = 0x0004,
            RestaurantId = 0x0006,
            All = ClientTag | AccessToken | UserCredentials
        }
    }
}